import { $set } from '@feng3d/serialization';
import { BufferAttribute3D, Clock, Color, FogExp23D, Mesh3D, MeshBasicMaterial3D, Node3D, PerspectiveCamera3D, PlaneGeometry3D, Scene3D, StatsComponent, TextureLoader3D, WebGLRenderer3D } from 'feng3d-three';
import { FirstPersonControls3D } from '../../extension/controls/FirstPersonControls3D';

// import Stats from 'three/addons/libs/stats.module.js';

const rootPath = '../../';

let camera: PerspectiveCamera3D;
let controls: FirstPersonControls3D;
let scene: Scene3D;
let renderer: WebGLRenderer3D;
let stats: StatsComponent;

let mesh: Mesh3D;
let geometry: PlaneGeometry3D;
let material: MeshBasicMaterial3D;
let clock: Clock;

const worldWidth = 128;
const worldDepth = 128;

init();
animate();

function init()
{
    camera = new Node3D().addComponent('PerspectiveCamera3D', { fov: 60, aspect: window.innerWidth / window.innerHeight, near: 1, far: 20000 });
    camera.entity.position.y = 200;

    clock = new Clock();

    scene = new Node3D().addComponent('Scene3D');
    scene.background = new Color(0xaaccff);
    scene.fog = new FogExp23D(0xaaccff, 0.0007);

    geometry = $set(new PlaneGeometry3D(), { width: 20000, height: 20000, widthSegments: worldWidth - 1, heightSegments: worldDepth - 1 });
    geometry.rotateX(-Math.PI / 2);

    const position = geometry.attributes.position as BufferAttribute3D;
    position.usage = 'DynamicDrawUsage';

    for (let i = 0; i < position.count; i++)
    {
        const y = 35 * Math.sin(i / 2);
        position.setY(i, y);
    }

    const texture = new TextureLoader3D().load(`${rootPath}textures/water.jpg`);
    texture.wrapS = texture.wrapT = 'RepeatWrapping';
    texture.repeat.set(5, 5);

    material = $set(new MeshBasicMaterial3D(), { color: { value: 0x0044ff }, map: texture });

    mesh = new Node3D().addComponent('Mesh3D', { geometry, material });
    scene.entity.addChild(mesh.entity);

    renderer = scene.addComponent('WebGLRenderer3D', { parameters: { antialias: true } });
    renderer.setPixelRatio(window.devicePixelRatio);
    renderer.setSize(window.innerWidth, window.innerHeight);
    document.body.appendChild(renderer.domElement);

    controls = new FirstPersonControls3D(camera, renderer.domElement);

    controls.movementSpeed = 500;
    controls.lookSpeed = 0.1;

    stats = scene.addComponent('StatsComponent');
    document.body.appendChild(stats.dom);

    //

    window.addEventListener('resize', onWindowResize);
}

function onWindowResize()
{
    camera.aspect = window.innerWidth / window.innerHeight;
    camera.updateProjectionMatrix();

    renderer.setSize(window.innerWidth, window.innerHeight);

    controls.handleResize();
}

//

function animate()
{
    requestAnimationFrame(animate);

    render();
    stats.update();
}

function render()
{
    const delta = clock.getDelta();
    const time = clock.getElapsedTime() * 10;

    const position = geometry.attributes.position as BufferAttribute3D;

    for (let i = 0; i < position.count; i++)
    {
        const y = 35 * Math.sin(i / 5 + (time + i) / 7);
        position.setY(i, y);
    }

    position.needsUpdate = true;

    controls.update(delta);
    renderer.render(scene, camera);
}
